'''
Created on Jun 9, 2012

@author: Timothy A. Mann
'''

import kryptos.text
from operator import itemgetter

def frequency(textStr, symbol):
    """
    Computes the frequency with which a specified symbol was used in a text string.
    
    @param textStr a string of text
    @param symbol the symbol to compute the frequency for
    @return the frequency of the specified symbol in the text string
    """
    return textStr.count(symbol) / float(len(textStr))

def frequency_map(textStr, symbols=None):
    """
    Computes the frequency of a set of symbols and stores them in a map.
    If the symbols argument is None, then a frequency map is generated for
    all of the text string's symbols.
    
    @param textStr a string of text
    @param symbols the set of symbols to calculate frequency for
    """
    fmap = {};
    if(symbols is None):
        symbols = kryptos.text.symbol_set(textString)
    for s in symbols:
        fmap[s] = frequency(textStr, s)

def ngram_counts_map(textStr, n, minCount=1):
    """
    Computes the number of times each n-gram occurs in a text string
    and stores each count in a dictionary from n-grams to counts.
    
    @param textStr a string of text
    @param n the size of n-grams in characters
    @return a map from n-grams to the number of times each n-gram appeared in the text
    """
    ltext = textStr.lower()
    textLength = len(textStr)
    cmap = {};
    for i in range(textLength):
        j = i + n
        if(j < textLength):
            ngram = textStr[i:j]
            if ngram in cmap:
                cmap[ngram] = cmap[ngram] + 1
            else:
                cmap[ngram] = 1
    delKeys = set()
    for key in cmap:
        if(cmap[key] < minCount):
            delKeys.add(key)
    for dkey in delKeys:
        del cmap[dkey]
    return cmap

def sort_map_by_value(map):
    """
    Returns a list of the key-value pairs from map sorted by the second
    entry (or value entry) in descending order.
    
    @param map a map from keys to ordered values
    """
    unsorted = []
    for (k,v) in map.items():
        unsorted.append((k,v))
    return sorted(unsorted, key=itemgetter(1), reverse=True)